package tool

import (
	"encoding/json"
	"fmt"
	"gorm.io/gorm"
	"reflect"
	"slices"
)

func ArrayColumn[T any, K any](list []T, fieldName string, unique bool) ([]K, error) {
	var result []K

	for _, item := range list {
		// 获取 item 的反射值
		itemValue := reflect.ValueOf(item)

		// 获取字段值
		fieldValue := itemValue.FieldByName(fieldName)
		if !fieldValue.IsValid() {
			return nil, fmt.Errorf("ArrayColumn field %s is not valid", fieldName)
		}

		// 类型断言和类型转换
		uniMap := make(map[any]bool)
		switch fieldValue.Interface().(type) {
		case K:
			_, ok := uniMap[fieldValue.Interface()]
			v := fieldValue.Interface().(K)
			if !unique || (unique && !ok) {
				uniMap[fieldValue.Interface()] = true
				result = append(result, v)
			}
		default:
			return nil, fmt.Errorf("ArrayColumn field %s has unexpected type %T", fieldName, fieldValue.Interface())
		}
	}

	return result, nil
}

func ArrayRelationList[T any, R any](db *gorm.DB, oriList []T, field string, fieldTo string, model R) (map[int][]R, error) {
	var fieldValueArr []int
	resultMapList := make(map[int][]map[string]any)
	for _, o := range oriList {
		value := reflect.ValueOf(o)
		fieldValue := value.FieldByName(field)
		v := int(fieldValue.Int())
		if v > 0 && !slices.Contains(fieldValueArr, v) {
			fieldValueArr = append(fieldValueArr, v)
			resultMapList[v] = []map[string]any{}
		}
	}

	var resultList []map[string]any

	db.Where(fmt.Sprintf("%s in (?)", fieldTo), fieldValueArr).Model(model).Find(&resultList)

	for _, r := range resultList {
		v, ok := r[fieldTo].(int)
		if ok {
			resultMapList[v] = append(resultMapList[v], r)
		}
	}

	var result map[int][]R
	jsonByte, err := json.Marshal(resultMapList)
	err = json.Unmarshal(jsonByte, &result)
	if err != nil {
		return nil, err
	}

	return result, nil
}
